#include <stdio.h>
#include <string.h>
#include <string>
#include <sstream>  


using namespace std;


void print_template_fonction(int n, int i)
{
	int nb_b=n;
	int tmp;
	printf("template <class E, class R");
	
	if(i>0)
		nb_b--;
		
	for(tmp=0; tmp<n; tmp++)
		printf(", class A%d", tmp+1);
	
	for(tmp=0; tmp<nb_b; tmp++)
		printf(", class B%d", tmp+1);
	
	printf(">\n");
}

void print_template_methode(int n, int i)
{
	int nb_b=n;
	int tmp;
	printf("template <class E, class R, template <");
	for(tmp=0; tmp<n+1; tmp++)
	{
		printf("class");
		if(tmp+1 <n+1)
		printf(", ");
	}
	printf("> class MF");
	
	if(i>0)
		nb_b--;
		
	for(tmp=0; tmp<n; tmp++)
		printf(", class A%d", tmp+1);
	
	for(tmp=0; tmp<nb_b; tmp++)
		printf(", class B%d", tmp+1);
	
	printf(">\n");
}

string sArgument(int n, int i)
{
	int tmp;
	ostringstream oss;

	for(tmp=0; tmp<n; tmp++)
	{
		oss << "A" << tmp+1;
		
		if(tmp+1<n)
			oss << ", ";
	}
		
	return oss.str();
}

string sList(int n, int i)
{
	int b=1;
	ostringstream oss;

	oss << "list" << n;
	if(n>0)
		oss << "<";
	for(int tmp=0; tmp<n; tmp++)
	{
		if(tmp+1 == i)
		{
			oss << "boost::arg<1> (*)()";
		}else
		{
			oss << "B" << b;
			b++;
		}
		
		if(tmp+1<n)
			oss << ", ";
		else
			oss << " >";
	}

	return oss.str();
}

void fonction(int n, int i)
{
	print_template_fonction(n,i);	// template <class R, class A1, class A2,...>
		 			
	if(i>0)
		printf("inline boost::function2 <void, A%d, E> toFunction( boost::_bi::bind_t	<\n", i);
	else
		printf("inline boost::function2 <void, Widget*, E> toFunction( boost::_bi::bind_t	<\n");
		 			
	printf("\t\t\t\t\t\t\t\t\t\t\tR,\n");
	printf("\t\t\t\t\t\t\t\t\t\t\tR (*)(%s),\n", sArgument(n,i).c_str());
		 			
	printf("\t\t\t\t\t\t\t\t\t\t\tboost::_bi::%s\n",sList(n,i).c_str());
	printf("\t\t\t\t\t\t\t\t\t\t> b, E* )\n");
	printf("{\n");
	printf("\treturn b;\n");
	printf("}\n\n");
}

void methode(int n, int i)
{
	if((n>0) && (n<9))
	{
			print_template_methode(n,i);	// template <class R, class A1, class A2,...>
				 			
			if(i>0)
			{
				if(i==1)
					printf("inline boost::function2 <void, A1*, E> toFunction( boost::_bi::bind_t	<\n");
				else
					printf("inline boost::function2 <void, A%d, E> toFunction( boost::_bi::bind_t	<\n", i);
			}
			else
				printf("inline boost::function2 <void, Widget*, E> toFunction( boost::_bi::bind_t	<\n");
				 			
			printf("\t\t\t\t\t\t\t\t\t\t\tR,\n");
	
			/*if(n==1)
				printf("\t\t\t\t\t\t\t\t\t\t\tMF<R, A1>,\n");
			else*/
				printf("\t\t\t\t\t\t\t\t\t\t\tMF<R, %s>,\n", sArgument(n,i).c_str());
	
			//printf("\t\t\t\t\t\t\t\t\t\t\tR (*)(%s),\n", sArgument(n,i).c_str());
				 			
			printf("\t\t\t\t\t\t\t\t\t\t\tboost::_bi::%s\n",sList(n,i).c_str());
			printf("\t\t\t\t\t\t\t\t\t\t> b, E* )\n");
			printf("{\n");
			printf("\treturn b;\n");
			printf("}\n\n");
	}
}



int tt=0;


void req(int restant, int nb)
{
	if(nb==0)
	{
		tt++;
		return;
	}
	
	if(restant>0)
		req(restant-1, nb-1);
	req(restant, nb-1);
}


int main()
{
	int nb;
	
	int n;
	int i;
	
	
	for(n=0; n<10; n++)	// Nombre d'argument
	{

		for(i=0; i<=n; i++)	// position de <1>
		{
			tt++;
				fonction(n,i);
				methode(n,i);
		}
	}
}












